package com.onpositive.wiki3.db.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;

import com.carrotsearch.hppc.IntArrayList;
import com.onpositive.compactdata.FuzzyStringMap;
import com.onpositive.wiki2.whole.model.ByteStringTable;
import com.onpositive.wiki3.db.ITitleMapper;
import com.onpositive.wiki3.db.IWikiDB;

public class TitleMapperImpl implements ITitleMapper {

	protected ByteStringTable tb;
	private IWikiDB db;

	public TitleMapperImpl(IWikiDB db, File pFile) throws Exception {
		ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(
				new FileInputStream(new File(pFile, "content.cat"))));
		tb = (ByteStringTable) is.readObject();
		is.close();
		this.db = db;
	}

	public int size() {
		return tb.size();
	}

	@Override
	public int getId(String title) {
		return tb.id(title);
	}

	// IntIntOpenHashMap map;
	// HashMap<String, IntArrayList> mm;
	FuzzyStringMap mq;

	@Override
	public int[] getFuzzyMatches(String title) {
		if (title.charAt(0) == ':') {
			title = title.substring(1);
		}
		if (title.length()==0){
			return new int[0];
		}
		int id = getId(title.replace('_', ' '));
		if (id != -1) {
			if (db.getContentAccessor().hasText(id)) {
				return new int[] { id };
			}
		}
		id = getId(title.replace(' ', '_'));
		if (id != -1) {
			if (db.getContentAccessor().hasText(id)) {
				return new int[] { id };
			}
		}
		String m = Character.toUpperCase(title.charAt(0)) + title.substring(1);
		id = getId(m.replace(' ', '_'));
		if (id != -1) {
			if (db.getContentAccessor().hasText(id)) {
				return new int[] { id };
			}
		}
		id = getId(m.replace('_', ' '));
		if (id != -1) {
			if (db.getContentAccessor().hasText(id)) {
				return new int[] { id };
			}
		}
		if (m.startsWith("Wikipedia_talk:")) {
			return new int[0];
		}
		if (mq == null) {
			buildFuzzy();
		}

		return mq.getMatches(title);

	}

	private void buildFuzzy() {
		if (new File(getPath()).exists()) {
			this.mq = new FuzzyStringMap(this);
			try {
				long l0 = System.currentTimeMillis();
				DataInputStream s = new DataInputStream(
						new BufferedInputStream(new FileInputStream(getPath())));
				mq.read(s);
				s.close();
				long l1 = System.currentTimeMillis();
				System.out.println(l1 - l0);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
			return;
		}
		HashMap<Integer, IntArrayList> mm = new HashMap<Integer, IntArrayList>();
		// map = new IntIntOpenHashMap();

		int size = tb.size();
		for (int a = 0; a < size; a++) {
			String name = tb.getName(a);
			String transform = transform(name);
			// int hashCode = transform.hashCode();

			IntArrayList arrayList = mm.get(transform.hashCode());
			if (arrayList == null) {
				arrayList = new IntArrayList();
				mm.put(transform.hashCode(), arrayList);
				// arrayList.add(a);
			}
			arrayList.add(a);
		}
		FuzzyStringMap ms = new FuzzyStringMap(this);
		for (Integer i : mm.keySet()) {
			ms.put(i.intValue(), mm.get(i).toArray());
		}
		try {
			DataOutputStream s = new DataOutputStream(new BufferedOutputStream(
					new FileOutputStream(getPath())));

			ms.write(s);
			s.close();
			this.mq = ms;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	protected String getPath() {
		return db.getPath() + "/" + "title.fuzzy";
	}

	private String transform(String catTitle) {
		return FuzzyStringMap.transform(catTitle);
	}

	@Override
	public String getTitle(int id) {
		return tb.getName(id);
	}

	@Override
	public int[] getAllFuzzyMatches(String object) {
		if (mq == null) {
			buildFuzzy();
		}
		return mq.getMatches(object);
	}

}
